#pragma once

#include <iostream>
#include <mysql/mysql.h>
#include "../comm/httplib.h"
#include "../comm/util.hpp"
#include "../comm/log.hpp"
#include "SqlHelper.hpp"

using namespace ns_log;
using namespace ns_util;
using namespace httplib;

typedef struct User_record
{
    std::string Machine_code;
    std::string Mail;
    std::string Password;
} Record;

bool Register(const std::string &User, const std::string &Email, const std::string &Password, const std::string &Machinecode, const std::string &Captcha, std::string *out)
{
    std::string sql;
    MYSQL *my = init_MYSQL();
    // 1.查询邮箱是否已存在
    std::string SelectSql = "select * from " + Emails_Tab + " where Email = '" + Email + "';";
    std::vector<Emails> emails;
    if(!CheckEmailExists(my, Email, out, &emails)){return false;}

    if (emails.size() == 0)
    {
        *out = "未发送验证码";
        return false;
    }
    else if (emails.size() == 1)
    {   
        int EmailId;
        int Machine_Id;
        GetEmailIdByEmail(my, Email, out, &EmailId);
        GetMachineIdByMachineCode(my, Machinecode, out, &Machine_Id);

        std::vector<EmailMachineAuths> emailMachineAuths;
        GetEmailMachineAuths(my, EmailId, Machine_Id, out, &emailMachineAuths);

        bool select_res_verify = emailMachineAuths[0].IsVerified;
        std::string real_captcha = emailMachineAuths[0].AuthCode;
        if (select_res_verify) {
            *out = "已验证";
            return false;
        }

        if (Captcha != real_captcha) {
            *out = "验证码错误";
            return false;
        }
        if(CheckUserNameExists(my, User, out))
        {
            *out = "用户名已存在";
        }
        std::cout << "Man" << std::endl;
        // 插入Users,Emails,MachineCodes
        std::string InsertSql = "insert into " + Users_Tab + "(UserName, Password, Create_time, Update_time)" + " values('" + User + "', '" + Password + "', '" + GetFormattedCurrentTime() + "', '" + GetFormattedCurrentTime() + "');";
        if (!DatabaseOperation<Users>(my, InsertSql, OperationType::INSERT, buildTableColumns<Users>(), out))
        {
            *out = "插入用户数据失败";
            return false;
        }
        // 获取UserID
        sql = "SELECT UserID from Users where UserName = '" + User + "';";
        std::vector<Users> UsersRes;
        DatabaseOperation<Users>(my, sql, OperationType::SELECT, buildTableColumns<Users>({"UserID"}), out, &UsersRes);
        int RecentUserId = UsersRes[0].UserID;
        // Update Emails表
        InsertSql = "update " + Emails_Tab + " set UserID = " + std::to_string(RecentUserId) + ", IsVerified = 1" + " where Email = '" + Email + "'";
        if (!DatabaseOperation<Emails>(my, InsertSql, OperationType::INSERT, buildTableColumns<Emails>(), out))
        {
            *out = "更新邮箱表失败";
            return false;
        }
        // Update MachineCode表
        InsertSql = "update " + MachineCodes_Tab + " set UserID = " + std::to_string(RecentUserId) + " where MachineCode = '" + Machinecode + "'";
        if (!DatabaseOperation<MachineCodes>(my, InsertSql, OperationType::INSERT, buildTableColumns<MachineCodes>(), out))
        {
            *out = "更新机器码表失败";
            return false;
        }
        
        // 更新EmailMachineAuths表中的IsVerified字段为1
        std::string UpdateAuthSql = "UPDATE " + EmailMachineAuths_Tab + " SET IsVerified = 1, AuthCode = '' WHERE EmailID = " + std::to_string(EmailId) + " and MachineID = " + std::to_string(Machine_Id) + ";";
        DatabaseOperation<EmailMachineAuths>(my, UpdateAuthSql, OperationType::INSERT, buildTableColumns<EmailMachineAuths>(), out);
    }
    return true;
}

bool Login_withCaptcha(MYSQL *my, const std::string &email, const std::string &captcha, const std::string &machineCode, std::string *out)
{
    // 1. 在Emails表中通过邮箱查找对应的EmailID
    std::vector<TableColumnInfo> emailsColumns = buildTableColumns<Emails>({"EmailID", "Email"});
    std::string selectEmailSql = "SELECT EmailID, Email FROM "+ Emails_Tab + " WHERE Email = '" + email + "';";
    std::vector<Emails> emailsResult;
    DatabaseOperation<Emails>(my, selectEmailSql, OperationType::SELECT, emailsColumns, out, &emailsResult);
    if (emailsResult.empty())
    {
        std::cerr << "Email not found in the database." << std::endl;
        *out = "Email not found in the database.";
        return false;
    }
    int EmailId = emailsResult[0].EmailID;

    // 获取MachineId
    std::vector<TableColumnInfo> MachineCodeColumns = buildTableColumns<MachineCodes>({"MachineID", "MachineCode"});
    selectEmailSql = "SELECT MachineID, MachineCode FROM "+ MachineCodes_Tab +" WHERE MachineCode = '" + machineCode + "';";
    std::vector<MachineCodes> MachineCodesResult;
    DatabaseOperation<MachineCodes>(my, selectEmailSql, OperationType::SELECT, MachineCodeColumns, out, &MachineCodesResult);
    if (MachineCodesResult.empty())
    {
        std::cerr << "Email not found in the database." << std::endl;
        *out = "Captcha not found in the database.";
        return false;
    }
    int MachineId = MachineCodesResult[0].MachineID;

    std::vector<TableColumnInfo> AuthsColunms = buildTableColumns<EmailMachineAuths>({"IsVerified", "AuthCode"});
    std::string selectAuthsSql = "select IsVerified, AuthCode FROM " + EmailMachineAuths_Tab + " WHERE MachineID = " + std::to_string(MachineId) + " AND EmailID = " + std::to_string(EmailId) + ";";
    std::vector<EmailMachineAuths> Result;
    DatabaseOperation<EmailMachineAuths>(my, selectAuthsSql, OperationType::SELECT, AuthsColunms, out, &Result);
    if (Result.empty())
    {
        std::cerr << "Not found Email AuthCode" << std::endl;
        *out = "Not found Email AuthCode";
        return false;
    }
    std::cout << "size: " << Result.size() << std::endl;
    bool isverified = Result[0].IsVerified;
    std::string Real_Captcha = Result[0].AuthCode;
    std::cout << "Real_Captcha: " << Real_Captcha << std::endl;
    if (captcha == Real_Captcha)
    {
        *out = "Auth successfully!";
        std::cout << "isverified" << std::endl;
        // 更新Email表中的IsVerified字段为1
        std::string UpdateEmailSql = "UPDATE " + Emails_Tab + " SET IsVerified = 1 WHERE EmailID = " + std::to_string(EmailId) + ";";
        DatabaseOperation<Emails>(my, UpdateEmailSql, OperationType::INSERT, buildTableColumns<Emails>(), out);

        // 更新EmailMachineAuths表中的IsVerified字段为1
        std::string UpdateAuthSql = "UPDATE " + EmailMachineAuths_Tab + " SET IsVerified = 1, AuthCode = '' WHERE EmailID = " + std::to_string(EmailId) + " and MachineID = " + std::to_string(MachineId) + ";";
        DatabaseOperation<EmailMachineAuths>(my, UpdateAuthSql, OperationType::INSERT, buildTableColumns<EmailMachineAuths>(), out);

        return true;
    }
    return false;
}

bool Login_withPwd(MYSQL *my, const std::string &email, const std::string &password, const std::string &machineCode, std::string *out)
{
    // 1. 在Emails表中通过邮箱查找对应的UserID
    std::vector<TableColumnInfo> emailsColumns = buildTableColumns<Emails>({"UserID", "Email"});
    std::string selectEmailSql = "SELECT UserID, Email FROM Emails WHERE Email = '" + email + "';";
    std::vector<Emails> emailsResult;
    DatabaseOperation<Emails>(my, selectEmailSql, OperationType::SELECT, emailsColumns, out, &emailsResult);
    if (emailsResult.empty())
    {
        std::cerr << "Email not found in the database." << std::endl;
        *out = "Email not found in the database.";
        return false;
    }
    int userIDFromEmail = emailsResult[0].UserID;

    // 2. 在Users表中通过用户ID和密码验证用户身份
    std::vector<TableColumnInfo> usersColumns = buildTableColumns<Users>({"UserID", "Password"});
    std::string selectUserSql = "SELECT UserID, Password FROM Users WHERE UserID = " + std::to_string(userIDFromEmail) + " AND Password = '" + password + "'";
    std::vector<Users> usersResult;
    DatabaseOperation<Users>(my, selectUserSql, OperationType::SELECT, usersColumns, out, &usersResult);
    if (usersResult.empty())
    {
        std::cerr << "Invalid password for the given user." << std::endl;
        *out = "Invalid password for the given user.";
        return false;
    }

    // 3. 在MachineCodes表中通过用户ID和机器码验证机器是否属于该用户
    // 用别的机器登录，需要重新验证
    std::vector<TableColumnInfo> machineCodesColumns = buildTableColumns<MachineCodes>({"UserID", "MachineCode"});
    std::string selectMachineCodeSql = "SELECT UserID, MachineCode FROM MachineCodes WHERE UserID = " + std::to_string(userIDFromEmail) + " AND MachineCode = '" + machineCode + "'";
    std::vector<MachineCodes> machineCodesResult;
    DatabaseOperation<MachineCodes>(my, selectMachineCodeSql, OperationType::SELECT, machineCodesColumns, out, &machineCodesResult);
    if (machineCodesResult.empty())
    {
        std::cerr << "Machine code is not associated with the given user." << std::endl;
        // 新的主机登录
        *out = "Please log in with the verification code.";
        return false;
    }

    return true;
}

std::string GetUserName(const std::string &email, std::string *response_str)
{
    MYSQL *my = init_MYSQL();
    // 1. 在Emails表中通过邮箱查找对应的UserID
    std::string selectEmailSql = "SELECT UserID FROM "+ Emails_Tab + " WHERE Email = '" + email + "';";
    std::vector<Emails> emailsResult;
    DatabaseOperation<Emails>(my, selectEmailSql, OperationType::SELECT, buildTableColumns<Emails>({"UserID"}), response_str, &emailsResult);
    if (emailsResult.empty())
    {
        std::cerr << "Email not found in the database." << std::endl;
    }
    int userIDFromEmail = emailsResult[0].UserID;
    std::vector<TableColumnInfo> UsersColumns = buildTableColumns<Users>({"UserName"});
    selectEmailSql = "SELECT UserName FROM " + Users_Tab + " WHERE UserID = " + std::to_string(userIDFromEmail) + ";";
    std::vector<Users> UsersResult;
    DatabaseOperation<Users>(my, selectEmailSql, OperationType::SELECT, UsersColumns, response_str, &UsersResult);
    if (emailsResult.empty())
    {
        std::cerr << "Email not found in the database." << std::endl;
    }
    return UsersResult[0].UserName;
}
//************ */
void Update_after_sendCaptcha(const std::string &email, const std::string &captcha, const std::string &machinecode, std::string *out)
{
    MYSQL *my = init_MYSQL();

    // 查询Email是否存在,存在更新，不存在插入
    std::string sql = std::string("SELECT EmailID FROM " + Emails_Tab + " where Email = '" + email + "';");
    std::vector<Emails> EmailsRes;
    int EmailId;
    if(!DatabaseOperation<Emails>(my, sql, OperationType::SELECT, buildTableColumns<Emails>({"EmailID"}), out, &EmailsRes))
    {
        std::cout << "Captcha: Email not found !" << std::endl;
    }
    if (EmailsRes.size() != 0)
    {
        // 更新Email表
        std::string UpdateSql = "update " + Emails_Tab + " set IsVerified = 0, Create_time = '" + GetFormattedCurrentTime() + "' where EmailID = " + std::to_string(EmailsRes[0].EmailID) + ";";
        DatabaseOperation<Emails>(my, UpdateSql, OperationType::INSERT, buildTableColumns<Emails>(), out);
    }
    else
    {
        std::string InsertSql = "insert into " + Emails_Tab + "(UserID, Email, IsVerified, Create_time)" + " values(" + std::to_string(-1) + ", '" + email + "' ,0 , '" + GetFormattedCurrentTime() + "');";
        if (!DatabaseOperation<Emails>(my, InsertSql, OperationType::INSERT, buildTableColumns<Emails>(), out))
        {
            std::cout << "Captcha: Insert Email Error !" << std::endl;
        }
    }
    GetEmailIdByEmail(my, email, out, &EmailId);
    std::cout << "Captcha: EmailId = " << EmailId << std::endl;

    // 查询MachineCode是否存在
    sql = "SELECT MachineID FROM " + MachineCodes_Tab + " WHERE MachineCode = '" + machinecode + "';";
    std::vector<MachineCodes> MachineCodesRes;
    DatabaseOperation<MachineCodes>(my, sql, OperationType::SELECT, buildTableColumns<MachineCodes>({"MachineID"}), out, &MachineCodesRes);
    int Machine_Id;

    if (MachineCodesRes.size() != 0)
    {
        // 更新MachineCode表
        Machine_Id = MachineCodesRes[0].MachineID;
        std::string UpdateSql = "UPDATE " + MachineCodes_Tab + " SET Create_time = '" + GetFormattedCurrentTime() + "' WHERE MachineID = " + std::to_string(Machine_Id) + ";";
        DatabaseOperation<MachineCodes>(my, UpdateSql, OperationType::INSERT, buildTableColumns<MachineCodes>(), out);
    }
    else
    {
        // 插入MachineCode表
        std::string InsertSql = "INSERT INTO " + MachineCodes_Tab + "(UserID, MachineCode, Create_time) VALUES(" + std::to_string(-1) + ", '" + machinecode + "', '" + GetFormattedCurrentTime() + "');";
        if (!DatabaseOperation<MachineCodes>(my, InsertSql, OperationType::INSERT, buildTableColumns<MachineCodes>(), out))
        {
            std::cout << "插入MachineCode数据失败" << std::endl;
        }
        // 查询插入的MachineCode对应的MachineID
        GetMachineIdByMachineCode(my, machinecode, out, &Machine_Id);
    }
    std::cout << "Machine_Id = " << Machine_Id << std::endl;

    // 查询EmailMachineAuths表中是否存在对应的EmailID和MachineID
    sql = "SELECT * FROM " + EmailMachineAuths_Tab + " WHERE EmailID = " + std::to_string(EmailId) + " AND MachineID = " + std::to_string(Machine_Id) + ";";
    std::vector<EmailMachineAuths> EmailMachineAuthsRes;
    DatabaseOperation<EmailMachineAuths>(my, sql, OperationType::SELECT, buildTableColumns<EmailMachineAuths>(), out, &EmailMachineAuthsRes);

    if (EmailMachineAuthsRes.size() != 0)
    {
        // 更新EmailMachineAuths表
        std::string UpdateSql = "UPDATE " + EmailMachineAuths_Tab + " SET AuthCode = '" + captcha + "', IsVerified = 0, Create_time = '" + GetFormattedCurrentTime() + "' WHERE EmailID = " + std::to_string(EmailId) + " AND MachineID = " + std::to_string(Machine_Id) + ";";
        DatabaseOperation<EmailMachineAuths>(my, UpdateSql, OperationType::INSERT, buildTableColumns<EmailMachineAuths>(), out);
    }
    else
    {
        // 插入EmailMachineAuths表
        std::string InsertSql = "INSERT INTO " + EmailMachineAuths_Tab + "(EmailID, MachineID, AuthCode, IsVerified, Create_time) VALUES(" + std::to_string(EmailId) + ", " + std::to_string(Machine_Id) + ", '" + captcha + "', 0, '" + GetFormattedCurrentTime() + "');";
        DatabaseOperation<EmailMachineAuths>(my, InsertSql, OperationType::INSERT, buildTableColumns<EmailMachineAuths>(), out);
    }
}